package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.base.BaseEntity;
import com.ruoyi.common.constant.CacheKeyConstants;
import com.ruoyi.common.constant.ResultConstants;
import com.ruoyi.common.enums.AmountType;
import com.ruoyi.common.enums.TxnType;
import com.ruoyi.common.exception.BusinessException;
import com.ruoyi.common.support.Convert;
import com.ruoyi.common.utils.*;
import com.ruoyi.system.domain.WdyTxnHistory;
import com.ruoyi.system.domain.WdyUser;
import com.ruoyi.system.domain.WdyWithdraw;
import com.ruoyi.system.mapper.WdyWithdrawMapper;
import com.ruoyi.system.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 提币记录 服务层实现
 * 
 * @author ruoyi
 * @date 2019-03-11
 */
@Service
public class WdyWithdrawServiceImpl extends ServiceImpl<WdyWithdrawMapper, WdyWithdraw> implements IWdyWithdrawService
{
	private Logger logger = LoggerFactory.getLogger(WdyWithdrawServiceImpl.class);
	@Autowired
	protected Environment environment;

	@Autowired
	private IWdyUserService wdyUserService;

	@Autowired
	private IWdyTxnHistoryService wdyTxnHistoryService;


	@Autowired
	private IRedisTemplateService redisTemplateService;

	@Autowired
	private ISysConfigService sysConfigService;

	/**
     * 查询提币记录信息
     * 
     * @param id 提币记录ID
     * @return 提币记录信息
     */
    @Override
	public WdyWithdraw selectWdyWithdrawById(Long id)
	{
	    return baseMapper.selectWdyWithdrawById(id);
	}
	
	/**
     * 查询提币记录列表
     * 
     * @param wdyWithdraw 提币记录信息
     * @return 提币记录集合
     */
	@Override
	public List<WdyWithdraw> selectWdyWithdrawList(WdyWithdraw wdyWithdraw)
	{
	    return baseMapper.selectWdyWithdrawList(wdyWithdraw);
	}
	public String getStatistics(WdyWithdraw wdyWithdraw){
		return baseMapper.getStatistics(wdyWithdraw);
	}
    /**
     * 新增提币记录
     * 
     * @param wdyWithdraw 提币记录信息
     * @return 结果
     */
	@Override
	public int insertWdyWithdraw(WdyWithdraw wdyWithdraw)
	{
	    return baseMapper.insertWdyWithdraw(wdyWithdraw);
	}
	
	/**
     * 修改提币记录
     * 
     * @param wdyWithdraw 提币记录信息
     * @return 结果
     */
	@Override
	public int updateWdyWithdraw(WdyWithdraw wdyWithdraw)
	{
	    return baseMapper.updateWdyWithdraw(wdyWithdraw);
	}

	/**
     * 删除提币记录对象
     * 
     * @param ids 需要删除的数据ID
     * @return 结果
     */
	@Override
	public int deleteWdyWithdrawByIds(String ids)
	{
		return baseMapper.deleteWdyWithdrawByIds(Convert.toStrArray(ids));
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public WdyWithdraw withdraw(WdyWithdraw withdraw) {
		if(StringUtils.isEmpty(withdraw.getUserId())) {
			throw new BusinessException(ResultConstants.FI1000, "用户id" + MessageUtils.message("not.null"));
		}



		if(withdraw.getAmountType() == null) {
			throw new BusinessException(ResultConstants.FI1000, "金额类型" + MessageUtils.message("not.null"));
		}

		AmountType amountType = AmountType.getByCode(withdraw.getAmountType());

		if((amountType == AmountType.VC || amountType == AmountType.VC_WITHDRAW) && StringUtils.isEmpty(withdraw.getWalletAddress())) {
			throw new BusinessException(ResultConstants.FI1000, "提币地址" + MessageUtils.message("not.null"));
		}

		BigDecimal withdrawAmount = withdraw.getAmount();
		if(withdrawAmount == null) {
			throw new BusinessException(ResultConstants.FI1000, "提币金额" + MessageUtils.message("not.null"));
		}

		withdrawAmount = BigDecimalUtil.getP2BigDecimal(withdrawAmount);

		if(withdrawAmount.compareTo(BigDecimal.ZERO) <= 0) {
			throw new BusinessException(ResultConstants.FI1000, "提币金额" + MessageUtils.message("param.error"));
		}

		BigDecimal minAmount = BigDecimal.ZERO;
		BigDecimal withdrawCommission = BigDecimal.ZERO;
		if(amountType == AmountType.CNN) {
			minAmount = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_min_amount"));
			withdrawCommission = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_commission"));
		} else if(amountType == AmountType.VC) {
			minAmount = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_vc_min_amount"));
			withdrawCommission = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_vc_commission"));
		} else if(amountType == AmountType.VC_WITHDRAW) {
			minAmount = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_vc_withdraw_min_amount"));
			withdrawCommission = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_vc_commission"));
		} else {
			throw new BusinessException(ResultConstants.FI1000, "amountType" + MessageUtils.message("param.error"));
		}

		if(withdrawAmount.compareTo(minAmount) < 0) {
			throw new BusinessException(ResultConstants.FI1000, "最小提币金额为" + String.format("%.2f", minAmount));
		}

		QueryWrapper<WdyUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("user_id", withdraw.getUserId());
		queryWrapper.eq("del_flag", BaseEntity.NOT_DELETED);
		WdyUser user = wdyUserService.getOne(queryWrapper);

		if(amountType == AmountType.CNN && withdrawAmount.compareTo(user.getCnnWithdrawAmount()) > 0) {
			throw new BusinessException(ResultConstants.FI2004, "账户余额不足");
		} else if(amountType == AmountType.VC && withdrawAmount.compareTo(user.getVcAmount()) > 0){
			throw new BusinessException(ResultConstants.FI2004, "账户余额不足");
		} else if(amountType == AmountType.VC_WITHDRAW && withdrawAmount.compareTo(user.getVcWithdrawAmount()) > 0){
			throw new BusinessException(ResultConstants.FI2004, "账户余额不足");
		}

		WdyUser updateUser = new WdyUser();
		if(amountType == AmountType.CNN) {
			updateUser.setCnnWithdrawAmount(BigDecimalUtil.subtract(user.getCnnWithdrawAmount(), withdrawAmount));
		} else if(amountType == AmountType.VC) {
			updateUser.setVcAmount(BigDecimalUtil.subtract(user.getVcAmount(), withdrawAmount));
		} else if(amountType == AmountType.VC_WITHDRAW) {
			updateUser.setVcWithdrawAmount(BigDecimalUtil.subtract(user.getVcWithdrawAmount(), withdrawAmount));
		}
		updateUser.setVersion(user.getVersion());
		QueryWrapper<WdyUser> userQueryWrapper = new QueryWrapper<>();
		userQueryWrapper.eq("user_id", user.getUserId());
		userQueryWrapper.eq("del_flag", BaseEntity.NOT_DELETED);
		if(!wdyUserService.update(updateUser, userQueryWrapper)) {
			throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
		}

		String txnId = redisTemplateService.getId(CacheKeyConstants.WITHDRAW_ID_TPL);
		BigDecimal actualAmount = BigDecimalUtil.getP2BigDecimal(BigDecimalUtil.subtract(withdrawAmount, withdrawCommission));
		withdraw.setWithdrawId(txnId);
		withdraw.setCommission(withdrawCommission);
		withdraw.setActualAmount(actualAmount);
		withdraw.setWithdrawStatus(WdyWithdraw.STATUS_PROCESSING);
		withdraw.setWithdrawTime(DateUtils.getNowDate());
		if(StringUtils.isNotEmpty(withdraw.getRemark())) {
			withdraw.setRemark(AESUtil.encrypt(withdraw.getRemark()));
		}
		save(withdraw);

		WdyTxnHistory txnHistory = new WdyTxnHistory();
		txnHistory.setUserId(user.getUserId());
		txnHistory.setTxnId(txnId);
		txnHistory.setTxnAmount(BigDecimalUtil.subtract(0, withdrawAmount));
		if(amountType == AmountType.CNN) {
			txnHistory.setTxnType(TxnType.WITHDRAW_CNN.getCode());
			txnHistory.setAmountType(TxnType.WITHDRAW_CNN.getAmountType().getCode());
			txnHistory.setTxnDesc(TxnType.WITHDRAW_CNN.getName());
		} else if(amountType == AmountType.VC) {
			txnHistory.setTxnType(TxnType.WITHDRAW_VC.getCode());
			txnHistory.setAmountType(TxnType.WITHDRAW_VC.getAmountType().getCode());
			txnHistory.setTxnDesc(TxnType.WITHDRAW_VC.getName());
		} else if(amountType == AmountType.VC_WITHDRAW) {
			txnHistory.setTxnType(TxnType.WITHDRAW_VC_WITHDRAW.getCode());
			txnHistory.setAmountType(TxnType.WITHDRAW_VC_WITHDRAW.getAmountType().getCode());
			txnHistory.setTxnDesc(TxnType.WITHDRAW_VC_WITHDRAW.getName());
		}
		wdyTxnHistoryService.save(txnHistory);

		return withdraw;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void withdrawConfirm(WdyWithdraw withdraw) {

		QueryWrapper<WdyWithdraw> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("withdraw_id", withdraw.getWithdrawId());
		queryWrapper.eq("withdraw_status", WdyWithdraw.STATUS_PROCESSING);
		queryWrapper.eq("del_flag", BaseEntity.NOT_DELETED);
		WdyWithdraw originWithdraw = getOne(queryWrapper);
		if(originWithdraw == null) {
			throw new BusinessException(ResultConstants.FI2005, "提币订单不存在");
		}

		if(originWithdraw.getWithdrawStatus() != WdyWithdraw.STATUS_PROCESSING) {
			throw new BusinessException(ResultConstants.FI2006, "提币订单状态错误");
		}

		QueryWrapper<WdyUser> userQueryWrapper = new QueryWrapper<>();
		userQueryWrapper.eq("user_id", withdraw.getUserId());
		userQueryWrapper.eq("del_flag", BaseEntity.NOT_DELETED);
		WdyUser user = wdyUserService.getOne(userQueryWrapper);

		AmountType amountType = AmountType.getByCode(originWithdraw.getAmountType());
		if(withdraw.getWithdrawStatus() == WdyWithdraw.STATUS_FAIL) {
			WdyUser updateUser = new WdyUser();
			if(amountType == AmountType.CNN) {
				updateUser.setCnnWithdrawAmount(BigDecimalUtil.add(user.getCnnWithdrawAmount(), originWithdraw.getAmount()));
			} else if(amountType == AmountType.VC) {
				updateUser.setVcAmount(BigDecimalUtil.add(user.getVcAmount(), originWithdraw.getAmount()));
			} else if(amountType == AmountType.VC_WITHDRAW) {
				updateUser.setVcWithdrawAmount(BigDecimalUtil.add(user.getVcWithdrawAmount(), originWithdraw.getAmount()));
			}
			updateUser.setVersion(user.getVersion());
			if(!wdyUserService.update(updateUser, userQueryWrapper)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}

			WdyTxnHistory txnHistory = new WdyTxnHistory();
			txnHistory.setUserId(originWithdraw.getUserId());
			txnHistory.setTxnId(originWithdraw.getWithdrawId());
			txnHistory.setTxnAmount(originWithdraw.getAmount());
			if(amountType == AmountType.CNN) {
				txnHistory.setTxnType(TxnType.WITHDRAW_CNN_BACK.getCode());
				txnHistory.setAmountType(TxnType.WITHDRAW_CNN_BACK.getAmountType().getCode());
				txnHistory.setTxnDesc(TxnType.WITHDRAW_CNN_BACK.getName());
			} else if(amountType == AmountType.VC) {
				txnHistory.setTxnType(TxnType.WITHDRAW_VC_BACK.getCode());
				txnHistory.setAmountType(TxnType.WITHDRAW_VC_BACK.getAmountType().getCode());
				txnHistory.setTxnDesc(TxnType.WITHDRAW_VC_BACK.getName());
			} else if(amountType == AmountType.VC_WITHDRAW) {
				txnHistory.setTxnType(TxnType.WITHDRAW_VC_WITHDRAW_BACK.getCode());
				txnHistory.setAmountType(TxnType.WITHDRAW_VC_WITHDRAW_BACK.getAmountType().getCode());
				txnHistory.setTxnDesc(TxnType.WITHDRAW_VC_WITHDRAW_BACK.getName());
			}
			wdyTxnHistoryService.save(txnHistory);
		}

        if(withdraw.getWithdrawStatus() == WdyWithdraw.STATUS_SUCCESS) {
			WdyWithdraw updateWithdraw = new WdyWithdraw();
			updateWithdraw.setWithdrawId(withdraw.getWithdrawId());
			updateWithdraw.setCommission(originWithdraw.getCommission());
			updateWithdraw.setActualAmount(originWithdraw.getActualAmount());
			updateWithdraw.setWithdrawStatus(withdraw.getWithdrawStatus());
			updateWithdraw.setRemitTime(DateUtils.getNowDate());
			updateWithdraw.setCompletedTime(DateUtils.getNowDate());
			if(!update(updateWithdraw, queryWrapper)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}

        } else {
			WdyWithdraw updateWithdraw = new WdyWithdraw();
			updateWithdraw.setWithdrawId(withdraw.getWithdrawId());
			updateWithdraw.setCommission(BigDecimal.ZERO);
			updateWithdraw.setActualAmount(BigDecimal.ZERO);
			updateWithdraw.setWithdrawStatus(withdraw.getWithdrawStatus());
			updateWithdraw.setCompletedTime(DateUtils.getNowDate());
			if(!update(updateWithdraw, queryWrapper)) {
				throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
			}
		}
	}

	@Transactional(rollbackFor = Exception.class)
	@Override
	public void autoWithdraw(WdyWithdraw wdyWithdraw) {
		wdyWithdraw = this.withdraw(wdyWithdraw);
		BigDecimal minAmount = new BigDecimal(sysConfigService.selectConfigByKey("withdraw_confirm_min_amount"));
		if(wdyWithdraw.getAmount().compareTo(minAmount) < 0) {
			wdyWithdraw = this.getById(wdyWithdraw.getId());
			wdyWithdraw.setWithdrawStatus(WdyWithdraw.STATUS_SUCCESS);
			this.withdrawConfirm(wdyWithdraw);
		}
	}

	@Override
	public BigDecimal getSum(WdyWithdraw wdyWithdraw) {
		return baseMapper.getSum(wdyWithdraw);
	}


	@Transactional(rollbackFor = Exception.class)
	@Override
	public void withdrawConsumeAmount(WdyWithdraw withdraw) {
		if(StringUtils.isEmpty(withdraw.getUserId())) {
			throw new BusinessException(ResultConstants.FI1000, "用户id" + MessageUtils.message("not.null"));
		}

		BigDecimal withdrawAmount = withdraw.getAmount();
		if(withdrawAmount == null) {
			throw new BusinessException(ResultConstants.FI1000, "充值金额" + MessageUtils.message("not.null"));
		}

		withdrawAmount = BigDecimalUtil.getP2BigDecimal(withdrawAmount);

		if(withdrawAmount.compareTo(BigDecimal.ZERO) <= 0) {
			throw new BusinessException(ResultConstants.FI1000, "充值金额" + MessageUtils.message("param.error"));
		}

		BigDecimal minAmount = BigDecimal.valueOf(100);
		BigDecimal withdrawCommission = BigDecimal.ZERO;

		if(withdrawAmount.compareTo(minAmount) < 0) {
			throw new BusinessException(ResultConstants.FI1000, "最小充值金额为" + String.format("%.2f", minAmount));
		}

		QueryWrapper<WdyUser> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("user_id", withdraw.getUserId());
		queryWrapper.eq("del_flag", BaseEntity.NOT_DELETED);
		WdyUser user = wdyUserService.getOne(queryWrapper);

		UpdateWrapper<WdyUser> updateWrapper = new UpdateWrapper<>();
		updateWrapper.eq("user_id", user.getUserId());
		updateWrapper.eq("version", user.getVersion());
		updateWrapper.eq("del_flag", BaseEntity.NOT_DELETED);
		updateWrapper.set("vc_consume_amount", BigDecimalUtil.subtract(user.getVcConsumeAmount(), withdrawAmount));
		if(!wdyUserService.update(updateWrapper)) {
			throw new BusinessException(ResultConstants.FI2007, "系统繁忙，请稍后重试");
		}

		String txnId = redisTemplateService.getId(CacheKeyConstants.WITHDRAW_ID_TPL);
		BigDecimal actualAmount = BigDecimalUtil.getP2BigDecimal(BigDecimalUtil.subtract(withdrawAmount, withdrawCommission));
		withdraw.setWithdrawId(txnId);
        withdraw.setAmountType(AmountType.VC_CONSUME.getCode());
		withdraw.setCommission(withdrawCommission);
		withdraw.setActualAmount(actualAmount);
		withdraw.setWithdrawStatus(WdyWithdraw.STATUS_SUCCESS);
        Date nowDate = DateUtils.getNowDate();
        withdraw.setWithdrawTime(nowDate);
        withdraw.setRemitTime(nowDate);
        withdraw.setCompletedTime(nowDate);
		withdraw.setRemark(AESUtil.encrypt("商城充值"));
		save(withdraw);

		WdyTxnHistory txnHistory = new WdyTxnHistory();
		txnHistory.setUserId(user.getUserId());
		txnHistory.setTxnId(txnId);
		txnHistory.setTxnAmount(withdrawAmount.negate());
		txnHistory.setTxnType(TxnType.WITHDRAW_VC_CONSUME.getCode());
		txnHistory.setAmountType(TxnType.WITHDRAW_VC_CONSUME.getAmountType().getCode());
		txnHistory.setTxnDesc("商城充值");
		wdyTxnHistoryService.save(txnHistory);
	}
}
